#include "CLComChain.h"


CLComChain::CLComChain()
{
}
CLComChain* CLComChain::GetChain()
{
    static CLComChain* _instance = new CLComChain;

	return _instance;
}
CLComChain::~CLComChain()
{
    map<CLComString, CChainItem*>::iterator it = m_mapIDItems.begin();
	for (; it != m_mapIDItems.end(); ++it)
	{
		delete it->second;
		it->second = nullptr;
	}

	m_mapIDItems.clear();
}
bool CLComChain::AddItem(CLComString id, CLComString fid, int itemType)
{
	EnterSection();

	if (FindChainItem(id))
	{
		LeaveSection();
		return true;
	}

	if (fid.GetLength() <= 0)
	{
		CChainItem* pitem = new CChainItem(id, NULL, itemType);

		m_mapIDItems[id] = pitem;

		LeaveSection();

		return true;
	}

    map<CLComString, CChainItem*>::iterator it =	m_mapIDItems.find(fid);
	if (it == m_mapIDItems.end())
	{
		LeaveSection();
		return false;
	}

	if (!it->second)
	{
		LeaveSection();
		return false;
	}
	if (it->second->GetSon(id))
	{
		LeaveSection();
		return true;
	}
	
	CChainItem* pitem = it->second->AddSon(id, itemType);

	m_mapIDItems[id] = pitem;

	LeaveSection();

	return true;
}
CLComString CLComChain::GetSonID(CLComString goalID, CLComString currentID)
{
	EnterSection();

	CChainItem* pGoal = FindChainItem(goalID);
 	if (!pGoal)
	{
		LeaveSection();
        return "";
	}
	CChainItem* pitem = FindSonChainItem(currentID, pGoal);

	if (pitem)
	{
		LeaveSection();
		return pitem->GetKey();
	}

	LeaveSection();

	return "";
}
int CLComChain::GetIDType(CLComString goalID)
{
	EnterSection();

	CChainItem* pItem = FindChainItem(goalID);
	if (pItem)
	{
		LeaveSection();
		return pItem->GetKeyObjType();
	}
	LeaveSection();

	return COMM_OBJECT_TYPE_OBJECT;
}
CLComString CLComChain::GetFChainItemByType(CLComString goalID, int itemType)
{
	EnterSection();

	CChainItem* pItem = FindChainItem(goalID);
	if (pItem)
	{
		CChainItem* pfather = pItem->GetFather();

		while (pfather)
		{
			if (pfather->GetKeyObjType() == itemType)
			{
				LeaveSection();
				return pfather->GetKey();
			}
			pItem = pfather;
			pfather = pfather->GetFather();
		}
	}
	LeaveSection();

	return "";
}

void CLComChain::UpgradeSonItem(CLComString id)
{
	CChainItem* pSonItem = FindChainItem(id);
	CChainItem* pFatherItem = pSonItem->GetFather();
	CChainItem* pGFatherItem = pFatherItem->GetFather();

	pFatherItem->DelSon(id);
	pGFatherItem->AddSon(pSonItem);
	pSonItem->m_pFather = pGFatherItem;

}

void CLComChain::DowngradeSonItem(CLComString predID,CLComString id)
{
	CChainItem* pSonItem = FindChainItem(id);
	CChainItem* pPreItem = FindChainItem(predID);
	pSonItem->m_pFather = pPreItem;

}

CChainItem* CLComChain::FindChainItem(CLComString id)
{
    map<CLComString, CChainItem*>::iterator it = m_mapIDItems.find(id);
	if (it != m_mapIDItems.end())
	{
		return it->second;
	}
	return NULL;
}
CChainItem* CLComChain::FindSonChainItem(CLComString id, CChainItem* goalItem)
{
	EnterSection();

	CChainItem* pItem = goalItem;
	CChainItem* pfather = goalItem->GetFather();

	while (pfather)
	{
		if (pfather->GetKey() == id)
		{
			break;
		}
		pItem = pfather;
		pfather = pfather->GetFather();
	}

	LeaveSection();

	return pItem;
}
void CLComChain::DelItem(CLComString id)
{
	EnterSection();

    map<CLComString, CChainItem*>::iterator it =	m_mapIDItems.find(id);
	if (it != m_mapIDItems.end())
	{
		CChainItem* pfather = it->second->GetFather();
		if (pfather)
		{
			pfather->DelSon(id);
		}
		delete it->second;
		it->second = nullptr;
		m_mapIDItems.erase(it);
	}

	LeaveSection();
}
